iT邦幫忙

2026 iThome 鐵人賽

DAY 24
0

前言

經過前幾天的消費記帳、查詢與分析功能後,今天終於進入 SubWise 的另一個核心功能:訂閱管理

這次的目標不是單純把訂閱資料寫進 Google Sheets,而是讓使用者可以直接透過自然語言告訴 SubWise「我要訂什麼、多少錢、多久扣一次」,剩下的資料整理與日期判斷交給 AI Agent 處理。這跟前幾天的消費記帳邏輯很像,但訂閱資料有一個消費記錄沒有的特性——它是「週期性」的,同一筆訂閱會被重複提到,也需要系統自己推算「下一次」什麼時候發生,這也是今天開發過程中花最多時間處理的部分。


今日實作實錄

一、確認訂閱資料的儲存能力

今天首先確認 Google Sheets 已經具備 Subscriptions 工作表,並讓 SubWise 可以讀取、寫入及更新訂閱資料。一筆訂閱資料包含七個欄位:

  • 服務名稱
  • 訂閱價格
  • 扣款週期
  • 下次扣款日期
  • 訂閱狀態
  • 分類
  • 備註

這個結構延續了先前訂閱功能已經建立的欄位設計,今天主要是重新確認這套機制在加入更多測試情境後依然穩定。其中「服務名稱已存在時更新原資料」的機制格外重要——如果使用者再次輸入:

幫我新增 Netflix,每月 390 元,8 月 25 日扣款

系統會先比對 Google Sheets 裡是否已經有同名服務,如果 Netflix 已經存在,SubWise 不會一直新增重複資料,而是直接找到原本那一列並更新內容。這也解決了訂閱管理很容易遇到的資料重複問題——使用者很可能會反覆提到同一個訂閱(例如先說金額,後來又補充扣款日),如果每次都新增一筆,Google Sheets 很快就會塞滿重複又互相矛盾的資料。

二、讓 AI 自動判斷訂閱資訊

接著把 Gemini 的自然語言解析結果串接到 subscription_service.py。例如使用者只需要輸入:

幫我新增 Canva,每月 300 元

Gemini 會把這句話轉換成結構化資料:

type: subscription
name: Canva
amount: 300
billing_cycle: monthly
next_billing_date: None
category: Subscription

值得注意的是,使用者這句話裡完全沒有提到「扣款日期」,Gemini 也很誠實地把 next_billing_date 留成 None,而不是自己亂猜一個日期。這是刻意的設計——AI 負責的是「理解使用者說了什麼」,而不是「補全使用者沒說的東西」,補全的工作交給後端邏輯,這樣資料的可信度才有保障。接著由後端負責補足缺少的資料,再寫入 Google Sheets。這讓使用者不需要知道 SubWise 背後有哪些欄位,也不需要記住固定的輸入格式,只需要像平常聊天一樣說話即可。

三、處理「沒有指定扣款日期」

這是今天比較重要的一個功能。如果使用者沒有告訴 SubWise 下一次什麼時候扣款,系統會依照訂閱週期自動推算。

例如「幫我新增 Canva,每月 300 元」,系統會取得今天的日期,判斷週期是 monthly,然後往後推算一個月,最後得到:

📅 下次扣款:2026-09-25

而年繳訂閱也需要用一樣的邏輯處理,只是推算的單位從「月」變成「年」。測試「幫我新增 Adobe Creative Cloud,每年 6000 元」時,系統成功推算出:

📅 下次扣款:2027-08-25

這代表推算邏輯不是寫死「固定加一個月」,而是有真正判斷 billing_cycle 的值(monthly / yearly)再決定推算的單位,因此使用者不需要每次建立訂閱時都提供完整資訊,SubWise 可以在資訊不完整時仍然給出合理的預設值。

四、處理「扣款日已經到了」的邊界情況

這是今天實作過程中發現的一個比較細節、但很重要的邊界狀況。

假設今天就是 8 月 25 日,使用者輸入:

幫我新增 Netflix,每月 390 元,8 月 25 日扣款

一開始的邏輯很直覺——使用者說了 8 月 25 日,那就把 next_billing_date 設成 8 月 25 日。但實際想一下就會發現這是錯的:如果今天就是 8 月 25 日,這一天已經過去(或正在發生),把它當成「下一次」扣款日期並不合理,使用者實際想表達的應該是「Netflix 每個月的固定扣款日是 25 號」,而不是「下一次扣款剛好是今天」。

因此加入了一層額外的日期判斷:

原扣款日已到期

判斷訂閱週期

每月 → 自動往後推一個月

2026-09-25

也就是說,系統會先檢查使用者提供的日期是否已經過去或就是今天,如果是,就依照訂閱週期自動往後推算到下一個週期。實際測試結果:

📌 服務:Netflix
💰 金額:NT$390
🔄 扣款週期:monthly
📅 下次扣款:2026-09-25

這讓「下一次扣款日期」真正符合使用者的期待,也是今天讓我花比較多時間反覆確認的一個小細節——這種邊界情況如果沒有特別測試,很容易在正常開發流程中被忽略,直到真的有人在扣款日當天新增訂閱才會發現問題。

五、加入訂閱查詢

新增功能確認沒問題後,也回頭確認了自然語言查詢流程可以正常運作。例如使用者問:

我有哪些訂閱?

或者:

Netflix 什麼時候扣款?

Gemini 可以把這些問題轉換成:

type: query
target: subscription
keyword: Netflix

再交給 query_service.py 查詢 Google Sheets,找出符合條件的訂閱資料並整理成回覆。這讓 SubWise 開始具備完整的訂閱管理閉環:

新增訂閱 → 儲存訂閱 → 查詢訂閱 → 取得扣款日期

也就是說,今天完成的不只是「把資料寫進去」,而是一條使用者可以真正來回互動的完整路徑——新增之後還能問回來,而不是資料寫進 Google Sheets 之後就再也看不到。


測試結果

今天實際測試了多種不同情境,逐一確認每個分支都能正確運作:

測試項目 結果
Netflix 每月 390 元,指定 8/25(扣款日已到期情境) ✅ 自動順延至下月
Canva 每月 300 元,未指定日期 ✅ 自動推算
Adobe Creative Cloud 每年 6000 元,未指定日期 ✅ 自動推算(年繳邏輯)
Microsoft 365 每年 2190 元,指定 10/15
Spotify 已存在訂閱再次建立 ✅ 更新原資料,未產生重複列
YouTube Premium 未指定日期 ✅ 自動推算
訂閱資料寫入 Google Sheets
訂閱資料從 Google Sheets 讀取

這八組測試涵蓋了「指定日期」「未指定日期」「月繳」「年繳」「重複訂閱」五種不同組合,代表目前訂閱建立與資料儲存的核心流程已經在多種情境下驗證過,而不只是單一情境下剛好能動。


今天遇到的真正 AI Agent 問題:API 配額限制

最後進行 LINE + Render 實測時,遇到了一個不是程式邏輯造成的問題。原本以為前面本機測試都已經通過,部署上去應該一路順利,結果 Render Log 顯示:

429 RESOURCE_EXHAUSTED
GenerateRequestsPerDayPerProject-FreeTier
limit: 20

也就是 Gemini Free Tier 的每日請求配額已經達到上限。一開始看到這個錯誤有點緊張,第一反應是「是不是今天新加的訂閱邏輯寫錯了」,於是回頭檢查程式碼,卻怎麼看都沒有明顯問題。

後來換個角度測試——直接在本機環境(不透過 Render)重新呼叫一次 Gemini,測試同樣的問句「Microsoft 365 什麼時候扣款?」,結果 Gemini 仍然可以正常解析,成功回傳:

{
    "type": "query",
    "target": "subscription",
    "period": "all",
    "keyword": "Microsoft 365"
}

這個對照測試很關鍵——本機可以正常呼叫 Gemini,代表程式邏輯本身沒有問題,問題出在 Render 這邊使用的 API Key(或專案)已經打到當日的請求上限。這也讓我第一次真正遇到 AI Agent 開發中「外部 API 配額限制」這個實際運維層面的問題,而不是單純的程式邏輯錯誤。

這也讓今天的除錯過程多了一個很重要的經驗:看到 AI 回覆失敗時,不能直接假設是程式寫錯,應該先從 Render Log 判斷真正的錯誤來源,並用「換一個環境重現」的方式來縮小問題範圍。


今日完成

  • 確認訂閱資料七欄位結構,支援讀取/寫入/更新
  • Gemini 訂閱意圖解析(自然語言 → subscription JSON)
  • 未指定扣款日期時自動推算(月繳/年繳皆支援)
  • 扣款日已到期時自動順延至下一個週期
  • 訂閱查詢意圖串接 query_service,支援關鍵字查詢
  • 完成 8 組不同情境的完整測試,涵蓋指定/未指定日期、月繳/年繳、重複訂閱
  • 確認 Render 端 Gemini API 配額限制問題,透過本機對照測試釐清非程式邏輯錯誤

目前訂閱建立與查詢的完整流程:

自然語言 → Gemini 意圖辨識 → subscription
→ 訂閱資料驗證 → 日期自動推算(含到期順延判斷)
→ 重複訂閱更新 → Google Sheets

自然語言 → Gemini 查詢意圖 → subscription query → Google Sheets → 訂閱資訊


明日預告

今天已經讓 SubWise 學會建立、更新與查詢訂閱,但距離「完整的訂閱管理 Agent」還差最後幾塊拼圖。明天將繼續完善訂閱功能,讓使用者不只是「知道有哪些訂閱」,而是可以進一步管理與掌握即將發生的扣款。
Day 25 的目標,是從「我可以把訂閱記下來」,進化成「SubWise 會幫我掌握訂閱、計算支出,甚至提醒我即將被扣款」。這一步完成後,SubWise 的訂閱管理才會真正從資料 CRUD,開始變成一個有 Agent 感的智慧生活功能。我們明天見!


上一篇
[Day 23] 一句話就能問帳:打造 SubWise 的自然語言財務搜尋引擎
系列文
AI 時代的輕量化開發:ChatGPT 打造 LINE 多模態記帳與續訂預警 Agent24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言